#ifndef _ESP_FFB_
#define _ESP_FFB_
#include "stdint.h"
#include "tinyusb.h"

#define AXIS_X 0
#define AXIS_Y 1

#define MAX_EFFECTS_NUM 12
#define DIRECTION_ENABLE 0x20
#define DEG_TO_RAD ((float)((float)PI / 180.0))
/*********************************设置或清除设备的 PID 状态*********************************************/
#define	PAUSE  						 (0b10000000)
#define	ACTUATOR_ENABLE 			 (0b01000000)
#define	SAFETY_SWITCH_ON 			 (0b00100000)
#define	ACTUATOR_OVERRIDE_SWITCH_ON  (0b00010000)
#define	ACTUATOR_POWER				 (0b00001000)
// 设置 Pause 状态
#define SET_PAUSE(state)           ((state).pid_state |= PAUSE)   // 设置 Pause 状态
#define CLEAR_PAUSE(state)         ((state).pid_state &= ~PAUSE)  // 清除 Pause 状态

// 设置 Actuator Enable 状态
#define SET_ACTUATOR_ENABLE(state) ((state).pid_state |= ACTUATOR_ENABLE)   // 设置 Actuator Enable 状态
#define CLEAR_ACTUATOR_ENABLE(state) ((state).pid_state &= ~ACTUATOR_ENABLE) // 清除 Actuator Enable 状态

// 设置 Safety Switch On 状态
#define SET_SAFETY_SWITCH_ON(state) ((state).pid_state |= SAFETY_SWITCH_ON)   // 设置 Safety Switch 状态
#define CLEAR_SAFETY_SWITCH_ON(state) ((state).pid_state &= ~SAFETY_SWITCH_ON) // 清除 Safety Switch 状态

// 设置 Actuator Override Switch On 状态
#define SET_ACTUATOR_OVERRIDE_SWITCH(state) ((state).pid_state |= ACTUATOR_OVERRIDE_SWITCH_ON)  // 设置 Actuator Override Switch 状态
#define CLEAR_ACTUATOR_OVERRIDE_SWITCH(state) ((state).pid_state &= ~ACTUATOR_OVERRIDE_SWITCH_ON)  // 清除 Actuator Override Switch 状态

// 设置 Actuator Power 状态
#define SET_ACTUATOR_POWER(state)  ((state).pid_state |= ACTUATOR_POWER)  // 设置 Actuator Power 状态
#define CLEAR_ACTUATOR_POWER(state) ((state).pid_state &= ~ACTUATOR_POWER) // 清除 Actuator Power 状态

// 初始化整个设备状态
#define INIT_ALL_STATE(state)     ((state).pid_state = ACTUATOR_ENABLE|ACTUATOR_POWER)  // 

// 检查是否处于 Pause 状态
#define IS_PAUSE(state)            (((state).pid_state & PAUSE) != 0)

// 检查是否启用 Actuators
#define IS_ACTUATOR_ENABLED(state) (((state).pid_state & ACTUATOR_ENABLE) != 0)

// 检查 Safety Switch 是否开启
#define IS_SAFETY_SWITCH_ON(state) (((state).pid_state & SAFETY_SWITCH_ON) != 0)

// 检查是否启用 Actuator Override Switch
#define IS_ACTUATOR_OVERRIDE_SWITCH_ON(state) (((state).pid_state & ACTUATOR_OVERRIDE_SWITCH_ON) != 0)

// 检查 Actuator Power 是否开启
#define IS_ACTUATOR_POWER_ON(state) (((state).pid_state & ACTUATOR_POWER) != 0)
// 设置播放状态
#define SET_BLOCK_STATE(state, block_number, enabled)   \
    ((state).effect_state = ((enabled) ? 0x80 : 0x00) | ((block_number) & 0x7F))  // 设置启用标志位（第一位）和 block 编号（后 7 位）

//ET Types
enum{
	CONSTANT = 1,
	RAMP,
	SQUARE,
	SINE,
	TRIANGLE,
	SAWTOOTH_UP,
	SAWTOOTH_DOWN,
	SPRING,
	DAMPER,
	INERTIA,
	FRICTION,
	CUSTOM
};


typedef enum {
    DC_Enable_Actuators = 1,   // 启用执行器
    DC_Disable_Actuators,      // 禁用执行器
    DC_Stop_All_Effects,       // 停止所有效果
    DC_Device_Reset,           // 设备重置
    DC_Device_Pause,           // 设备暂停
    DC_Device_Continue         // 设备继续
} DeviceControlCommand;



#define HAT_SWITCH_NORTH            0
#define HAT_SWITCH_NORTH_EAST       1
#define HAT_SWITCH_EAST             2
#define HAT_SWITCH_SOUTH_EAST       3
#define HAT_SWITCH_SOUTH            4
#define HAT_SWITCH_SOUTH_WEST       5
#define HAT_SWITCH_WEST             6
#define HAT_SWITCH_NORTH_WEST       7
#define HAT_SWITCH_NULL             8
#define INFINITE_DURATION           (-1)
#include <stdint.h>

//*******************输入报告**********************/
// 定义用于表示按钮的结构体
typedef struct {
    uint8_t button1 : 1;
    uint8_t button2 : 1;
    uint8_t button3 : 1;
    uint8_t button4 : 1;
    uint8_t button5 : 1;
    uint8_t button6 : 1;
    uint8_t button7 : 1;
    uint8_t button8 : 1;
    uint8_t button9 : 1;
    uint8_t button10 : 1;
    uint8_t button11 : 1;
    uint8_t button12 : 1;
    uint8_t button13 : 1;
    uint8_t button14 : 1;
    uint8_t button15 : 1;
    uint8_t button16 : 1;
} Buttons;

// 定义用于表示方向键（Hat Switch）的结构体
typedef struct TU_ATTR_PACKED{
    uint8_t hat_switch : 4;  // 4位方向信息
} HatSwitch;

// 定义用于表示模拟摇杆的结构体
typedef struct TU_ATTR_PACKED{
    uint16_t X;  // 摇杆X轴值
    uint16_t Y;  // 摇杆Y轴值
    uint16_t Z;  // 摇杆Z轴值
    uint16_t Rz; // 摇杆Rz轴值
} AnalogStick;

// 定义整个操纵杆的报告结构体
// typedef struct TU_ATTR_PACKED{
//     Buttons buttons[8];       // 按钮状态
//     HatSwitch hat_switch;  // 方向键状态
//     AnalogStick analog_stick;  // 摇杆数据
// } JoystickReport;
typedef TU_ATTR_PACKED struct {
    // 按钮部分：64 个按钮，每个占 1 bit
    struct {
        uint8_t buttons[8];  // 8 bytes = 64 bits (button1 在 buttons[0] 的 bit0)
    };
    
    // 轴部分：8 个 16-bit 有符号整数
    struct {
        int16_t X;      // 摇杆 X 轴
        int16_t Y;      // 摇杆 Y 轴
        int16_t Z;      // 摇杆 Z 轴
        int16_t Rx;     // 绕 X 轴旋转
        int16_t Ry;     // 绕 Y 轴旋转
        int16_t Rz;     // 绕 Z 轴旋转
        int16_t Dial;   // 旋钮
        int16_t Slider; // 滑块
    } axes;
} JoystickReport;
//设备状态
typedef struct{
	uint8_t pid_state;
	uint8_t effect_state;
}DeviceState;

//*************FEATURE 报告****************/
//effect block 下载状态
typedef enum{
	SUCCESS = 1,
	OUT_OF_MEMORY,
	ERROR,
}BlockLoadState;
typedef struct 
{
    uint8_t effect_block_index; // index dell'effetto
    uint8_t block_load_status; // 1 ok, 2 -out of memory, 3 JC was here, or maybe not ? case: undefined.
    uint16_t ram_pool_available;
    
}PidBlockLoadReport;

//**************输出报告的相关数据结构****************/

typedef union
{
	struct TU_ATTR_PACKED _set_condition_struct
	{
		uint8_t report_id;
		uint8_t usage_effect_block_index;  
		uint8_t parameter_block_offset_ordinals; 	// high 4 bits |low 4 bits 链接条件参数块的时候，特定类型的报告必须另外（除block index外）具有参数块偏移，但不是引用偏移，而是引用目标轴的索引（这是必要的，因为多个条件参数块可能是同一效果的一部分；与其他特定类型的块不同。）
		int8_t cp_offset;							// 标准化中心点偏移。偏离轴0位置。
		int8_t positive_coefficient; 				// 中性位置正侧的归一化系数常数
		int8_t negative_coefficient;				// 中性位置负侧的归一化系数常数
		uint8_t positive_saturation;				// 归一化最大正向力输出。
		uint8_t negative_saturation;				// 归一化最大负向力输出。
		uint8_t dead_band;							// 死区
	}set_condition_struct;
uint8_t array_entry[sizeof(struct _set_condition_struct)];
}SetConditionReport;


typedef union 
{
	struct TU_ATTR_PACKED _set_custom_force_report
	{
		uint8_t report_id;
		uint8_t effect_block_index;
		short int custom_force_data_offset;
		uint8_t custom_force_data[12];

	}set_custom_force_report;
	uint8_t array_entry[sizeof(struct _set_custom_force_report)];
} SetCustomForceReport;

typedef union
{ //usage table page 200
	struct TU_ATTR_PACKED
	{
		uint8_t report_id;//1
		uint8_t effect_block_index;				// 效果块索引
		uint8_t effect_type;						// 效果类型 参见 <EtType> //不能改成EtType类型，否则会出问题，必须对齐
		int16_t duration;						// 总持续时间 ms 如果对效果应用了包络，则将应用起始，然后是无限持续。
		int16_t trigger_repeat_interval;    	// 自动重复间隔，用于播放按住触发按钮触发的效果。间隔是播放效果结束和下一个效果开始之间的时间。如果此效果是一次性效果（不需要自动重复），则应将此值设置为INFINITE（Null）。
		int16_t sample_period;					// 设备应播放效果的时段。值为0表示应使用默认播放采样率。如果设备无法以指定的速率播放效果，它将选择最接近请求值的支持速率。
		uint8_t gain;							// 应用于效果的增益。这是一个归一化的缩放因子，应用于效果的所有恒力参数块和包络参数块。
		
		uint8_t trigger_button;					// 用于触发此效果播放的按钮的标识符或偏移量。空触发按钮值表示此效果未与按钮绑定。
		uint8_t axes_enable_direction; 			// 0b X|Y|Dir|00000 axes enable表示是否启用相关的轴，如果设置direction enable，则忽略“axes enable”标志，只定义一个条件参数块，并将“direction”作为极轴方向应用于该块。
		uint8_t direction_with_ordinals_1;		// X axis 方向，单位度，物理最大值36000
		uint8_t direction_with_ordinals_2;		// Y axis
		int16_t usage_undefined_1;// no ideea//15
	}set_effect_report;
	uint8_t array_entry[16];
} SetEffectReport;

typedef union
{
	struct TU_ATTR_PACKED
	{
		uint8_t report_id;
		uint8_t effect_block_index;	
		uint8_t magnitude; 			//如果将“包络”应用于此效果，则该值表示“包络”的 magnitude。如果未应用“包络”，则该值表示整个效果的振幅。
		int8_t offset; 				//该效果产生的力的范围为（偏移-幅值）到（偏移+幅值）。偏移成员的值也是应用于效果的任何封套的基线。
		uint8_t phase; 				//相位 0=0，255=3600°
		int16_t period;				//周期
	}set_periodic_report;
	uint8_t array_entry[7];
} SetPeriodicReport;

typedef union
{
	struct TU_ATTR_PACKED _set_constant_force_report
	{
		uint8_t report_id;
		uint8_t effect_block_index;
		int16_t magnitude;
		
	}set_constant_force_report;
	uint8_t array_entry[sizeof(struct _set_constant_force_report)];
}SetConstantForceReport;

typedef union
{
	struct TU_ATTR_PACKED _set_ramp_force_report
	{
		uint8_t report_id;
		uint8_t effect_block_index;
		int8_t start;
		int8_t end;
		
	}set_ramp_force_report;
	uint8_t array_entry[sizeof(struct _set_ramp_force_report)];
}SetRampForceReport;

typedef union 
{
	struct TU_ATTR_PACKED _envelopeReport
	{
		uint8_t  reportId;               // 报告id
		uint8_t  effectBlockIndex;       // 效果块索引
		uint8_t  attackLevel;            // 起点的归一化振幅
		uint8_t  fadeLevel;              // 结束的归一化包络
		uint16_t attackTime;          // 达到维持水平的过渡时间
		uint16_t fadeTime;			  // 达到结束振幅的过渡时间 单位ms
		/* data */
	}EnvelopeReport;
	uint8_t array_entry[sizeof(struct _envelopeReport)];
	/* data */
}SetEnvelopeReport;
typedef union {
	SetConditionReport Condition[2];
	SetCustomForceReport Custom;
	SetConstantForceReport Constant;
	SetRampForceReport Ramp;
	SetPeriodicReport Periodic;
}SpecialEffectPara;
typedef union 
{
	struct TU_ATTR_PACKED _squareReport
	{
		uint8_t  reportId;               // 报告id
		uint8_t  effectBlockIndex;       // 效果块索引
		uint8_t  attackLevel;            // 起点的归一化振幅
		uint8_t  fadeLevel;              // 结束的归一化包络
		uint16_t attackTime;          // 达到维持水平的过渡时间
		uint16_t fadeTime;			  // 达到结束振幅的过渡时间 单位ms
		/* data */
	}SquareReport;
	uint8_t array_entry[sizeof(struct _squareReport)];
	/* data */
}SetSquareReport;

typedef enum{
	MEFFECTSTATE_FREE = 0x00,
	MEFFECTSTATE_ALLOCATED,
}EffectState;

//一个效果的数据结构

typedef struct 
{
	EffectState State;
	SetEffectReport EffectPara;
	SpecialEffectPara SpecialPara;
	// SetConditionReport ConditionPara[2];
	SetEnvelopeReport *EnveLpoePara;
	//SetPeriodicReport *PeriodicPara;
	// ...
}Force_t;


//内存池结构体
typedef struct {
	uint8_t UsedCount;
	Force_t ForcesPool[MAX_EFFECTS_NUM]; //max 
}RamPool;

typedef enum {
	STOPPED,
	PLAYING,
	PAUSED
}PlayState;
//播放管理
typedef struct {
	uint8_t index; //播放的力效的块索引，注意是块索引，ram池中的索引 = 块索引 -1
	uint8_t PlayState; //播放的状态
	int16_t Timoffset;//播放的时间
	uint8_t Playnum
}Playing_t;

typedef struct {
	uint8_t count; //播放列表的数量,从0开始
	Playing_t PlayList[MAX_EFFECTS_NUM]; //播放列表
}PlayingManager;

typedef struct{
	int32_t AngleX;
	int32_t AngleY;
	//JoystickReport JoyStick;
	DeviceState deviceState;
	uint8_t AxisVelocity[2];
	uint8_t AxisAcceleration[2];
}WorldModel;

typedef struct{
	int32_t X;
	int32_t Y;
}ForceValue_t;


//内存池相关API
uint8_t GetNextIndex(void);
void InitRamPool(void);
void FreeAllBlocks(void);


extern PidBlockLoadReport _pidBlockLoadReport;
extern WorldModel worldModel;
extern PlayingManager EffectPlayingManager;
// extern RamPool _RamPool;
//创建效果相关的API
void CreateNewEffect(uint8_t reportID,const uint8_t *hid_report_out,uint8_t length);
void HandleOutput(const uint8_t* buffer,uint16_t bufsize);
float ApplyWheelAngleLimit(float angle,float value);
uint8_t USBSetDataEffect();
//播放管理相关的API
void PlayingManagerInit(PlayingManager *PlayingManager);
void PlayingManagerUpdate(PlayingManager *PlayingManager); //定时更新一次
void Add2Play(PlayingManager *PlayingManager,uint8_t index,uint8_t loop);
void StopPlay(PlayingManager *PlayingManager,uint8_t index);
void PausePlay(PlayingManager *PlayingManager,uint8_t index);
void StartPlay(PlayingManager *PlayingManager,uint8_t index);
void Output(PlayingManager *_PlayingManager,QueueHandle_t Queue);
void InitFFB(void);
#endif
